package com.zeyu.soc.log.spi.impl;

import java.io.IOException;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.NotFoundException;

import com.zeyu.soc.log.spi.TransformDescriptor;
import com.zeyu.soc.log.spi.TransformHandler;
import com.zeyu.soc.log.tools.MacroUtils;
import com.zeyu.soc.log.utils.ExceptionUtils;

/**
 * 处理未捕获异常.
 */
public class TraceExceptionTransformHandler implements TransformHandler {

	// ================================================================
	// Constants
	// ================================================================

	// ================================================================
	// Fields
	// ================================================================

	// ================================================================
	// Constructors
	// ================================================================

	// ================================================================
	// Methods from/for super Interfaces or SuperClass
	// ================================================================

	@Override
	public boolean canHandler(TransformDescriptor injectDescriptor) {
		if (null == injectDescriptor) {
			return false;
		}
		boolean canHandler = true;
		if (!TraceExceptionTransformDescriptor.class.isAssignableFrom(injectDescriptor.getClass())) {
			canHandler = false;
		}
		String clazzName = injectDescriptor.getNeedInjectClassName();
		Class<?> clazz = null;
		try {
			clazz = Class.forName(clazzName);
		} catch (ClassNotFoundException e) {
			canHandler = false;
		}
		if (null != clazz && !Throwable.class.isAssignableFrom(clazz)) {
			canHandler = false;
		}
		return canHandler;
	}

	@Override
	public byte[] transform(TransformDescriptor injectDescriptor) {

		TraceExceptionTransformDescriptor descriptor = (TraceExceptionTransformDescriptor) injectDescriptor;
		try {
			// 通过包名获取类文件
			CtClass cc = ClassPool.getDefault().get(descriptor.getNeedInjectClassName());
			// 获得无参构造方法
			CtConstructor[] constructors = cc.getConstructors();
			for (CtConstructor constructor : constructors) {
				constructor.insertAfter(MacroUtils
						.safeInsertTemplate("printStackTrace(com.zeyu.soc.log.tools.Trace.out);"));
			}
			return cc.toBytecode();
		} catch (NotFoundException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
		} catch (CannotCompileException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
		} catch (IOException e) {
			ExceptionUtils.addThrowable(e);
			e.printStackTrace();
			// 忽略异常处理
		}
		return null;
	}

	// ================================================================
	// Public or Protected Methods
	// ================================================================

	// ================================================================
	// Getter & Setter
	// ================================================================

	// ================================================================
	// Private Methods
	// ================================================================

	// ================================================================
	// Inner or Anonymous Class
	// ================================================================

	// ================================================================
	// Test Methods
	// ================================================================
}
